$.extend({
    /**
     * 获取当前页面所有的get参数
     * @returns {{}}
     */
    getPageParam() {
        return $.getQueryParam(window.location.search);
    },
    /**
     * 获取传入的查询串
     * @param query
     * @returns {{}}
     */
    getQueryParam(query = "") {
        const reg = /([^?=&]+)=([^?=&]+)/g
        const param = {};
        query.replace(reg, (...arg) => {
            param[arg[1]] = decodeURIComponent(arg[2])
        })
        return param;
    },

    /**
     * url参数的包装方法
     * @param url url
     * @param param 附加的参数
     * @param transfer 页面需要透传的参数
     * @returns {string}
     */
    sUrl(url, param = {}, transfer = ["token"]) {

        const pageParam = $.getPageParam();
        const transferParam = {};
        transfer.forEach(key => {
            transferParam[key] = pageParam[key];
        });

        param = {...transferParam, ...param}

        if (url.indexOf('?') >= 0) {
            const [newUrl, query] = url.split('?');
            url = newUrl;
            param = {...$.getQueryParam(query), ...param};
        }

        return url + "?" + $.param(param);
    },
    /**
     * 获取表单内容
     * @param $form jquery的form对象
     * @returns {{}}
     */
    getFormData($form) {
        if (!$form || $form.length === 0) {
            return {};
        }
        const data = {};
        $form.serializeArray().forEach(item => {
            const name = item.name;
            data[name] = $.trim(item.value);
        })
        return data;
    },
    /**
     * 简单包装ajax(代入一些默认值和loading)
     * @param param
     * @returns {*}
     */
    sAjax(param) {
        param = {
            timeout: 80000,
            type: 'post',
            async: true,
            showLoading: true,
            beforeSend: Function(),
            complete: Function(),
            ...param
        }

        if (param.showLoading) {
            const beforeSend = param.beforeSend;
            const complete = param.complete;

            let $loadingWidget;
            param.beforeSend = () => {
                $loadingWidget = $.loading();
                beforeSend();
            }

            param.complete = () => {
                complete();
                $loadingWidget.remove();
            }
        }

        return $.ajax(param);
    },

    /**
     * 带有回调的ajax调用
     * @param param
     * @param callback
     * @returns {*}
     */
    sApi(param, callback = Function()) {
        param = {
            ...param,
            success: res => {
                if (typeof res === "string") {
                    try {
                        res = JSON.parse(res);
                    } catch (e) {
                        res = {
                            Code: -14444,
                            Message: "返回格式不是JSON"
                        }
                    }
                }

                //登录异常
                if (res.Code === -11000) {
                    window.parent.location.href = "/admin/login.html";
                }

                callback(res);
            },
            error() {
                callback({
                    Code: -14444,
                    Message: "网络响应超时"
                });
            }
        }

        const {token} = $.getPageParam();
        if (token) {
            param.headers = {
                Authorization: `Bearer ${token}`
            }
        }


        return $.sAjax(param);
    },

    /**
     * 自定义的loading
     * @param msg
     * @returns {*|jQuery|HTMLElement}
     */
    loading(msg = "加载中...") {
        const $widget = $(`
            <div class="mask">
                <p class="mask-tip" style="background-color:#FFF;color:#333">
                <img alt="" width="30" src="/ui/pc/images/loading.gif" style="margin-right: 15px">${msg}</p>
            </div>
        `);
        $('body').append($widget);
        return $widget;
    },

    /**
     * 自定义的toast
     * @param msg
     * @param time
     * @param callback
     */
    toast(msg = "", time = 3000, callback = Function()) {
        const $widget = $(`<div class="mask"></div>`);
        if (msg instanceof jQuery) {
            $widget.append(msg);
        } else {
            $widget.append('<p class="mask-tip">' + msg + '</p>');
        }

        $('body').append($widget);

        $widget.on("click", () => {
            $widget.remove();
            callback();
        });

        setTimeout(() => {
            $widget.remove();
            callback();
        }, time);
    },

    /**
     * 自定义的dialog
     * @param content
     * @param param
     * @returns {*|jQuery|HTMLElement}
     */
    dialog(content, param = {}) {
        param = {
            title: "提示",
            width: "400px",
            okTitle: "确定",
            cancelTitle: "取消",
            init: Function(),
            ok: Function(),
            cancel: Function(),
            ...param
        }

        const $widget = $(`
            <div class="mask">
                <div class="msg-mask" style="width: ${param.width}">
                    <h5 data-type="title">${param.title}<i class="fr bi-x-lg" data-type="close"></i></h5>
                    <div class="clearfix tip-p" data-type="content"></div>
                    <div class="mask-btn" data-type="btnGroup"></div>
                </div>
            </div>
        `);

        const $contentWrap = $widget.find('[data-type="content"]');
        const $btnGroupWrap = $widget.find('[data-type="btnGroup"]');

        //弹窗内容插入，支持jquery对象
        $contentWrap.append(content);

        const {ok, cancel} = param;
        if (ok || cancel) {
            if (cancel) {
                const $cancelBtn = $(`<a class="c-btn btn-bg-gray m-r" href="javascript:;">${param.cancelTitle}</a>`);
                $btnGroupWrap.append($cancelBtn);
                $cancelBtn.on("click", () => {
                    if (cancel() !== false) {
                        $widget.remove();
                    }
                });
            }

            if (ok) {
                const $okBtn = $(`<a class="c-btn btn-bg-blue" href="javascript:;">${param.okTitle}</a>`);
                $btnGroupWrap.append($okBtn);
                $okBtn.on("click", () => {
                    if (ok() !== false) {
                        $widget.remove();
                    }
                })
            }
        } else {
            //无操作按钮，移除按钮组
            $btnGroupWrap.remove();
        }

        $widget.find('[data-type="close"]').on("click", () => {
            if (cancel) {
                if (cancel() !== false) {
                    $widget.remove();
                }
            } else {
                $widget.remove();
            }
        })

        //运行初始化
        param.init($contentWrap);

        $('body').append($widget);
        return $widget;
    },

    /**
     * 模态的select比较复杂，提供了一个动态获取select的方法
     * @param name
     * @param list
     * @param callback
     * @returns {*|jQuery|HTMLElement}
     */
    getSelect(name, list = [], callback = Function()) {
        list = list || [{
            name: '请选择',
            value: ''
        }];

        const $widget = $(`
            <span class="input-select">
                <input type="text" value="${list[0].name}"  readonly />
                <i class="bi-chevron-down"></i>
                <ul class="select-ul c-hide"></ul>
            </span>
        `);

        const $input = $(`<input type="hidden" name="${name}" value="${list[0].value}">`);
        $widget.prepend($input);

        const $ul = $widget.find('ul');
        list.forEach(({value, name}, index) => {
            const $li = getLi(value, name, index === 0);
            $ul.append($li);
        });

        $widget.on("click", () => {
            $widget.find('ul').show();
            return false;
        })

        $('body').on("click", () => {
            $widget.find('ul').hide();
        })

        //刷新list
        $widget.refreshList = (newList = []) => {
            $ul.html("");
            list = newList || [{
                name: '请选择',
                value: ''
            }];
            list.forEach(({value, name}, index) => {
                const $li = getLi(value, name, index === 0);
                $ul.append($li);
            });
        }

        $widget.setValue = (value) => {
            const filterList = list.filter(item => item.value === value);
            if (!filterList || filterList.length === 0) {
                return;
            }
            const info = filterList[0];
            $input.val(info.value);
            $input.siblings("input").val(info.name);
        }

        return $widget;

        function getLi(value, name, currFlag = false) {
            const $li = $(`<li class="${currFlag ? "curr" : ""}" data-value="${value}" title="${name}">${name}</li>`);
            $li.on("click", () => {
                $li.addClass("curr").siblings().removeClass("curr");
                $input.val(value);
                $input.siblings("input").val(name);
                $widget.find('ul').hide();
                callback({value, name});
                return false;
            });

            return $li;
        }
    },
    /**
     * 获取城市选择控件
     * @param param
     * @returns {*|jQuery|HTMLElement}
     */
    getCitySelect(param) {
        param = {
            level: 3,
            placeholder: null,
            provinceId: null,
            cityId: null,
            areaId: null,
            callback: Function(),
            dataSource(callback = Function()) {
                queryJson(({Code, Message, Result}) => {
                    if (Code !== 10000) {
                        return $.toast(Message);
                    }
                    callback(Result);
                });
            },

            ...param
        };

        if (!param.placeholder) {
            const placeholderDict = {1: "请选择省份", 2: "请选择省/市", 3: "请选择省/市/区"}
            param.placeholder = placeholderDict[param.level];
        }


        const $widget = $(`
            <span class="input-select">
                <input type="text" placeholder="${param.placeholder}"  readonly />
                <i class="bi-chevron-down"></i>
                <span class="city-select-wrap" style="display: none">
                    <ul class="city-select-tab"></ul>
                    <ul class="city-select-content"></ul>
                </span>
            </span>
        `);

        const $wrap = $widget.find('.city-select-wrap');
        const $tab = $wrap.find('.city-select-tab');
        const $content = $wrap.find('.city-select-content');

        $widget.on("click", () => {
            $wrap.show();
            return false;
        })

        $('body').on("click", () => {
            $wrap.hide();
        })

        $tab.on("click", "li", function () {
            $(this).addClass("curr").siblings().removeClass("curr");
        });

        $content.on("click", "li", function () {
            $(this).addClass("curr").siblings().removeClass("curr");
        });

        const $provinceTab = $('<li>省份</li>');
        const $cityTab = $('<li>城市</li>');
        const $areaTab = $('<li>区县</li>');

        $tab.append($provinceTab);
        if (param.level === 2 || param.level === 3) {
            $tab.append($cityTab);
        }
        if (param.level === 3) {
            $tab.append($areaTab);
        }

        let areaList = [];
        let currAreaInfo = {
            provinceId: null,
            provinceName: null,
            cityId: null,
            cityName: null,
            areaId: null,
            areaName: null
        };

        param.dataSource(list => {
            areaList = list;

            //初始化数据
            if (param.areaId) {
                currAreaInfo = {
                    ...currAreaInfo,
                    ...areaList.filter(({areaId}) => param.areaId === areaId)[0]
                };
            } else if (param.cityId) {
                currAreaInfo = {
                    ...currAreaInfo,
                    ...areaList.filter(({cityId, areaId}) => !areaId && param.cityId === cityId)[0]
                };
            } else if (param.provinceId) {
                currAreaInfo = {
                    ...currAreaInfo,
                    ...areaList.filter(({provinceId, cityId}) => !cityId && param.provinceId === provinceId)[0]
                };
            }

            const {provinceName, cityName, areaName} = currAreaInfo;

            $widget.find("input").val(`${provinceName || ""} ${cityName || ""} ${areaName || ""}`)

            $provinceTab.addClass("curr");
            initProvinceList();
        });

        $provinceTab.on("click", () => {
            initProvinceList();
        })

        $cityTab.on("click", () => {
            initCityList();
        })

        $areaTab.on("click", () => {
            initAreaList();
        })

        return $widget;

        function initProvinceList() {
            $content.html("");
            if (areaList.length === 0) {
                return;
            }

            areaList.filter(({cityId, areaId}) => !cityId && !areaId).forEach(item => {
                const {provinceId, provinceName} = item;
                const $li = $(`<li>${provinceName}</li>`);
                $content.append($li);
                if (currAreaInfo.provinceId === provinceId) {
                    $li.addClass("curr");
                }
                $li.on("click", () => {
                    currAreaInfo = item;
                    if (param.level === 1) {
                        selectCallback(currAreaInfo)
                    } else {
                        $cityTab.click();
                    }
                });
            });
        }

        function initCityList() {
            $content.html("");
            if (areaList.length === 0) {
                return;
            }

            if (!currAreaInfo.provinceId) {
                return;
            }

            areaList.filter((
                {
                    provinceId,
                    cityId,
                    areaId
                }
            ) => !areaId && cityId && provinceId === currAreaInfo.provinceId).forEach(item => {
                const {cityId, cityName} = item;
                const $li = $(`<li>${cityName}</li>`);
                $content.append($li);
                if (currAreaInfo.cityId === cityId) {
                    $li.addClass("curr");
                }
                $li.on("click", () => {
                    currAreaInfo = item;
                    if (param.level === 2) {
                        selectCallback(currAreaInfo)
                    } else {
                        $areaTab.click();
                    }
                });
            });

        }

        function initAreaList() {
            $content.html("");
            if (areaList.length === 0) {
                return;
            }

            if (!currAreaInfo.cityId) {
                return;
            }

            areaList.filter((
                {
                    cityId,
                    areaId
                }
            ) => areaId && cityId === currAreaInfo.cityId).forEach(item => {
                const {areaId, areaName} = item;
                const $li = $(`<li>${areaName}</li>`);
                $content.append($li);
                if (currAreaInfo.areaId === areaId) {
                    $li.addClass("curr");
                }
                $li.on("click", () => {
                    currAreaInfo = item;
                    selectCallback(currAreaInfo);
                });
            });
        }

        function selectCallback(currAreaInfo) {
            const {provinceName, cityName, areaName} = currAreaInfo;
            $widget.find("input").val(`${provinceName || ""} ${cityName || ""} ${areaName || ""}`)
            if (param.callback(currAreaInfo) !== false) {
                setTimeout(() => {
                    $wrap.hide();
                }, 1)
            }
        }

        function queryJson(callback = Function()) {
            $.sApi({
                url: "/Area/queryJson",
                showLoading: false,
            }, callback)
        }
    },
    /**
     * 一个公共的列表页面构建工具
     * @param $warp
     * @param $pager
     * @param column
     * @param dataSource
     */
    commonList(
        {
            $warp,
            $pager = null,
            column = [
                {title: "导航1", value: "valueName", class: "mtb2 w800", style: "width:80%"},
                {
                    title: "导航1", value(data, $td, index) {
                    }, class: "mtb2 w800", style: "width:80%"
                },
            ],
            dataSource = (currPage = 1, callback = Function(...{list: null, total: null, pageSize: null})) => {

            },
        }
    ) {
        let currPage = 1;

        if (!$pager) {
            $pager = $(`<div></div>`);
            $warp.append($pager);
        }

        const $table = $(`<table class="table table-hover"></table>`);
        $warp.prepend($table);

        const $tableHead = getThead();
        $table.append($tableHead);
        initData(currPage);

        return {
            getPage(page) {
                initData(page);
            },
            $table
        };


        function initData(page) {
            if (page) {
                currPage = page
            } else {
                page = currPage;
            }

            $tableHead.siblings().remove();
            $pager.html("");

            $tableHead.after(getTableMsg("数据加载中"));
            dataSource(page, (list, total, pageSize) => {
                $tableHead.siblings().remove();
                if (typeof list === "string") {
                    return $tableHead.after(getTableMsg(list));
                }

                if (!list || !(list?.length || 0)) {
                    return $tableHead.after(getTableMsg("暂无数据"));
                }

                $tableHead.after(getTbody(list));
                $pager.html($.getPager(page, total, pageSize, (page) => {
                    initData(page);
                }));
            })

        }

        function getTbody(list = []) {
            const $widget = $('<tbody class="tbale-h"></tbody>');
            list.forEach((data, index) => {
                const $tr = $(`<tr></tr>`);
                column.forEach((item, index) => {

                    const $td = $(`<td class="${item.class || ""}" style="${item.style || ""}"></td>`);

                    let content;
                    if (typeof item.value === "function") {
                        content = item.value(data, $td, index);
                    } else {
                        content = data[item.value];
                    }

                    if (content || content === 0) {
                        $td.html(content);
                    }
                    
                    $tr.append($td);
                });

                $widget.append($tr);
            });
            return $widget;
        }

        function getThead() {
            const $widget = $(`<thead data-type="tableHeadWidget"><tr></tr></thead>`);
            const $tr = $widget.find('tr');
            column.forEach((item) => {
                const $th = $(`<th class="${item.class || ""}" style="${item.style || ""}"></th>`);

                let title;
                if (typeof item.title === "function") {
                    title = item.value($th);
                } else {
                    title = item.title;
                }

                if (!title && title !== 0) {
                    title = "";
                }

                $th.html(title);
                $tr.append($th);
            });
            return $widget;
        }

        function getTableMsg(msg = "暂无数据") {
            return $(`
                <tbody class="tbale-h">
                    <tr>
                        <td colspan="${column.length}" style="background: #FFFFFF">
                            <div class="page-404">
                                <img src="/ui/pc/images/no-data.png" style="width: 200px;height: 90px;margin: 20px auto 0" alt="">
                                <p class="mt-30 mb-30">${msg}</p>
                            </div>
                        </td>
                    </tr>
                </tbody>
            `)
        }

    },

    /**
     * 一个分页组件
     * @param currPage
     * @param total
     * @param pageSize
     * @param callback
     */
    getPager(currPage = 1, total = 10, pageSize = 10, callback = Function(...{page: null})) {
        const totalPage = Math.ceil(total / pageSize);
        if (totalPage <= 1) {
            return "";
        }

        const $widget = $('<ul class="pagination pagination-lg"></ul>');
        const list = Array.from({length: totalPage}, (v, i) => i + 1);
        const lastPage = currPage - 1;
        const nextPage = currPage + 1;

        if (currPage > 1) {
            const $li = $(`<li><a href="javascript:;"><i class="bi-arrow-left"></i></a></li>`);
            $widget.append($li);
            $li.find("a").on("click", () => {
                callback(lastPage);
            })
        }

        const groupNum = 6;
        if (totalPage > 15) {
            if (currPage < groupNum || currPage > totalPage - groupNum) {
                list.splice(groupNum, totalPage - groupNum * 2);
                list.splice(groupNum, 0, "");
            }

            if (currPage >= groupNum && currPage <= totalPage - groupNum) {
                let startNumber = groupNum / 2;
                let spliceLength = currPage - groupNum;
                list.splice(startNumber, spliceLength);
                list.splice(startNumber, 0, "");

                startNumber = startNumber + 1 + groupNum;
                spliceLength = list.length - startNumber - groupNum / 2;
                list.splice(startNumber, spliceLength);
                list.splice(startNumber, 0, "");
            }
        }


        list.forEach((page, index) => {
            const $li = $(`
                <li class="${typeof page === "string" ? "lue" : ""} ${page === currPage ? "curr" : ""}">
                    <a href="javascript:;">${typeof page === "string" ? "..." : page}</a>
                </li>
            `)

            $widget.append($li);

            if (typeof page !== "string") {
                $li.find("a").on("click", () => {
                    callback(page);
                })
            }
        });

        if (currPage < totalPage) {
            const $li = $(`<li><a href="javascript:;"><i class="bi-arrow-right"></i></a></li>`);
            $widget.append($li);
            $li.find("a").on("click", () => {
                callback(nextPage);
            })
        }

        return $widget;
    }

})

/**
 * 页面js跳转
 */
$(document).on("click", "[data-jump]", function () {
    const href = $(this).attr('data-jump');
    if (!href) {
        location.reload();
    } else {
        location.href = $.sUrl(href);
    }
});


